/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.ufes.gpf.sgm.dao;

import edu.ufes.gpf.sgm.model.Endereco;
import edu.ufes.gpf.sgm.model.Pessoa;
import edu.ufes.gpf.sgm.observer.Observador;
import java.util.List;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.TreeSet;

/**
 *
 * @author Guilherme
 */
public class PessoasDAOMySQL extends AbstractDAOMySQL<Pessoa> {

    private static PessoasDAOMySQL instancia;
    private List<Observador> observadores;

    private PessoasDAOMySQL() throws ClassNotFoundException, SQLException {
        conectar();
        observadores = new ArrayList<Observador>();
    }

    public static PessoasDAOMySQL getInstancia() throws ClassNotFoundException, SQLException {
        if (instancia == null) {
            instancia = new PessoasDAOMySQL();
        }
        return instancia;
    }

    @Override
    public boolean salvar(Pessoa pObjeto) {
        try {
            consultar("INSERT INTO Endereco (cidade, uf, logradouro) VALUE ('"
                    + pObjeto.getEndereco().getCidade()
                    + "', '"
                    + pObjeto.getEndereco().getUF()
                    + "', '"
                    + pObjeto.getEndereco().getLogradouro()                    
                    + "')");
            
            consultar("INSERT INTO Pessoa (nomeCompleto, CPF, telefone, apelido, endereco) VALUE ('"
                    + pObjeto.getNomeCompleto()
                    + "', '"
                    + pObjeto.getCPF()
                    + "', '"
                    + pObjeto.getTelefone()
                    + "', '"
                    + pObjeto.getApelido()
                    + "', "
                    + "last_insert_id()"
                    + ")");            
            notificarObserver();
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean atualizar(Pessoa pObjeto) {
        try {
            consultar("UPDATE Pessoa SET "
                    + "nomeCompleto = '" + pObjeto.getNomeCompleto()
                    + "', CPF = '" + pObjeto.getCPF()
                    + "', telefone = '" + pObjeto.getTelefone()
                    + "', apelido = '" + pObjeto.getApelido()
                    + "' WHERE objectIdentifier = " + pObjeto.getId());

            consultar("UPDATE Endereco SET "
                    + "logradouro = '" + pObjeto.getEndereco().getLogradouro()
                    + "', cidade = '" + pObjeto.getEndereco().getCidade()
                    + "', UF = '" + pObjeto.getEndereco().getUF()
                    + "' WHERE objectIdentifier = " + pObjeto.getEndereco().getId());
            notificarObserver();
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean remover(Pessoa pObjeto) {
        try {
            consultar("DELETE FROM Pessoa WHERE (nomeCompleto = '" + pObjeto.getNomeCompleto()
                    + "' AND objectIdentifier = "
                    + pObjeto.getId()
                    + ")");
            notificarObserver();
            return true;
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public Pessoa buscarPorId(int pObjetoId) {
        try {
            ResultSet rs = consultar("SELECT p.objectIdentifier, p.nomeCompleto, p.apelido, p.CPF, p.telefone, p.endereco, e.objectIdentifier, e.logradouro, e.cidade, e.UF "
                    + "FROM Pessoa p INNER JOIN Endereco e "
                    + "ON e.objectIdentifier = p.endereco "
                    + "WHERE p.objectIdentifier = " + pObjetoId);
            rs.next();
            Pessoa retorno;
            if (rs.getRow() == 0) {
                retorno = null;
            } else {
                Endereco e = new Endereco(rs.getString("e.cidade"), rs.getString("e.UF"), rs.getString("e.logradouro"));
                e.setId(rs.getInt("e.objectIdentifier"));
                retorno = new Pessoa(rs.getString("p.nomeCompleto"), rs.getString("p.CPF"), rs.getString("p.telefone"), rs.getString("p.apelido"), e);
                retorno.setId(rs.getInt("p.objectIdentifier"));
            }
            return retorno;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public int ultimoObjectIdentifier() {
        try {
            ResultSet rs = consultar("SELECT MAX(objectIdentifier) FROM Pessoa");
            rs.next();
            int retorno;
            if (rs.getRow() == 0) {
                retorno = 0;
            } else {
                retorno = rs.getInt("MAX(objectIdentifier)");
            }
            return retorno;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

    @Override
    public Collection<Pessoa> buscarTodos() {
        try {
            ResultSet rs = consultar("SELECT p.objectIdentifier, p.nomeCompleto, p.apelido, p.CPF, p.telefone, p.endereco, e.objectIdentifier, e.logradouro, e.cidade, e.UF "
                    + "FROM Pessoa p INNER JOIN Endereco e "
                    + "ON e.objectIdentifier = p.endereco");
            Collection<Pessoa> retorno = new TreeSet<Pessoa>();
            while (rs.next()) {
                Endereco e = new Endereco(rs.getString("e.cidade"), rs.getString("e.UF"), rs.getString("e.logradouro"));
                e.setId(rs.getInt("e.objectIdentifier"));
                Pessoa p = new Pessoa(rs.getString("p.nomeCompleto"), rs.getString("p.CPF"), rs.getString("p.telefone"), rs.getString("p.apelido"), e);
                p.setId(rs.getInt("p.objectIdentifier"));
                retorno.add(p);
            }
            return retorno;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }

    public Collection<Pessoa> buscarPorNome(String pNome) {
        try {
            Collection<Pessoa> retorno = new TreeSet<Pessoa>();

            ResultSet rs = consultar("SELECT p.objectIdentifier, p.nomeCompleto, p.apelido, p.CPF, p.endereco, e.objectIdentifier, e.logradouro, e.cidade, e.UF "
                    + "FROM Pessoa p INNER JOIN Endereco e "
                    + "ON e.objectIdentifier = p.endereco "
                    + "WHERE p.nomeCompleto LIKE '%" + pNome + "%'");

            while (rs.next()) {
                Pessoa pessoa;
                Endereco e = new Endereco(rs.getString("e.cidade"), rs.getString("e.UF"), rs.getString("e.logradouro"));
                e.setId(rs.getInt("e.objectIdentifier"));
                pessoa = new Pessoa(rs.getString("p.nomeCompleto"), rs.getString("p.CPF"), rs.getString("p.telefone"), rs.getString("p.apelido"), e);
                pessoa.setId(rs.getInt("p.objectIdentifier"));
                retorno.add(pessoa);
            }

            return retorno;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public Collection<Pessoa> buscarPorApelido(String pApelido) {
        try {
            Collection<Pessoa> retorno = new TreeSet<Pessoa>();

            ResultSet rs = consultar("SELECT p.objectIdentifier, p.nomeCompleto, p.apelido, p.CPF, p.endereco, e.objectIdentifier, e.logradouro, e.cidade, e.UF "
                    + "FROM Pessoa p INNER JOIN Endereco e "
                    + "ON e.objectIdentifier = p.endereco "
                    + "WHERE p.apelido LIKE '%" + pApelido + "%'");

            while (rs.next()) {
                Pessoa pessoa;
                Endereco e = new Endereco(rs.getString("e.cidade"), rs.getString("e.UF"), rs.getString("e.logradouro"));
                e.setId(rs.getInt("e.objectIdentifier"));
                pessoa = new Pessoa(rs.getString("p.nomeCompleto"), rs.getString("p.CPF"), rs.getString("p.telefone"), rs.getString("p.apelido"), e);
                pessoa.setId(rs.getInt("p.objectIdentifier"));
                retorno.add(pessoa);
            }

            return retorno;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void addObserver(Observador o) {
        observadores.add(o);
    }

    @Override
    public void removerObserver(Observador o) {
        observadores.remove(o);
    }

    @Override
    public void notificarObserver() {
        Iterator<Observador> it = observadores.iterator();
        while (it.hasNext()) {
            Observador observador = it.next();
            observador.atualizar();
        }
    }
}
